package com.competition.web.admin.log.impl;

import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.ibatis.binding.MapperMethod.ParamMap;
import org.apache.ibatis.mapping.BoundSql;

import com.common.util.StringUtil;
import com.competition.web.admin.service.ITableColumnInfoService;
import com.competition.web.admin.util.SpringBeanUtil;
import com.competition.web.entity.LogContentWithBLOBs;

public abstract class AbstractLog {

	protected String getTableName(BoundSql boundSql) {

		String sql = boundSql.getSql();
		// update a set
		String updateTableSet = sql.substring(sql.indexOf("into") + 4, sql.indexOf("("));

		return updateTableSet.replace("\n", "").replace("\t", "").trim();

	}

	/**
	 * 是否记录日志
	 * 
	 * @param tableName 表名
	 * @return
	 */
	protected boolean recordLog(String tableName) {

		return -1 != tableName.indexOf("ums_admin_login_log") || tableName.startsWith("mg_log");
	}

	protected void cleanNoNeedData(Map<String, Object> map) {
		map.remove("updateTime");
		map.remove("createTime");
	}

	protected Map<String, Object> cleanNull(Map<String, Object> map) {

		Map<String, Object> dataNotNull = new HashMap<>();

		for (Map.Entry<String, Object> entry : map.entrySet()) {
			String key = entry.getKey();
			Object val = entry.getValue();

			if (null == val) {
				continue;
			}

			dataNotNull.put(key, val);
		}

		return dataNotNull;

	}

	protected <T, C> T getPropertyValue(String name, Class<C> target, Object param) throws NoSuchMethodException,
			SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {

		String methodName = StringUtil.generateGetMethodString(name);

		Method method = target.getMethod(methodName);

		return (T) method.invoke(param);

	}

	protected String getServiceName(String tableName) {

		String serviceName = tableName.replace("mg_", "");

		String[] serviceAppend = serviceName.split("_");

		serviceName = serviceAppend[0];

		for (int i = 1; i < serviceAppend.length; i++) {

			serviceName = serviceName.concat(StringUtil.toUpperByFirstChar(serviceAppend[i]));
		}

		return serviceName.concat("ServiceImpl");
	}

	/**
	 * 移除相同的数据
	 * 
	 * @param mapOrigialData
	 * @param newData
	 */
	protected Map<String, Object> removeTheSame(Map<String, Object> mapOrigialData, Map<String, Object> newData) {

		Map<String, Object> map = new HashMap<>();

		Object newObj, val;
		String key;

		for (Map.Entry<String, Object> entry : mapOrigialData.entrySet()) {
			key = entry.getKey();
			val = entry.getValue();

			val = val == null ? "" : val;

			newObj = newData.get(key);

			newObj = newObj == null ? "" : newObj;

			if (!newObj.equals(val)) {
				map.put(key, val);
			}
		}

		return map;
	}

	protected Map<String, Object> getDataToMap(Object data) throws NoSuchMethodException, SecurityException,
			IllegalAccessException, IllegalArgumentException, InvocationTargetException {

		System.out.println("data" + data);
		
		Class<?> target = data.getClass();

		Field[] fields = target.getDeclaredFields();

		String name;

		Object value;

		Map<String, Object> map = new HashMap<>();

		for (Field field : fields) {

			if (Modifier.isStatic(field.getModifiers())) {
				continue;
			}

			name = field.getName();
			value = this.getPropertyValue(name, target, data);

			map.put(name, value);
		}

		return map;

	}

	protected Object[] parseData(Object param) {

		Object[] data = null;

		if (param.getClass().isArray()) {
			// 数据是数组

			int len = Array.getLength(param);

			data = new Object[len];

			for (int i = 0; i < len; i++) {
				data[i] = Array.get(param, i);
			}
		} else if (param instanceof List) {

			List<Object> objectList = (List<Object>) param;

			int len = objectList.size();

			data = new Object[len];

			for (int i = 0; i < len; i++) {
				data[i] = objectList.get(i);
			}

		} else if (param instanceof ParamMap) {
			
			
			ParamMap<?> paramMap = (ParamMap<?>) param;
			
			Object object = paramMap.get("array");
			
			if (object instanceof List) {
				
				List<?> list = (List<?>) object;
				
				data = list.toArray();
 			} else if (object.getClass().isArray()) {
				data = (Object[]) object;
			}
			
		} else {
			data = new Object[1];

			data[0] = param;
		}

		return data;
	}

	/**
	 * 
	 * @return
	 */
	protected <V> int getId(V entity, Class<?> target) {

		try {

			Field idField = target.getDeclaredField("id");

			Object idValue = this.getPropertyValue(idField.getName(), target, entity);

			String idString = idValue.toString();

			return Integer.valueOf(idString).intValue();
		} catch (Exception e) {
			throw new Error(e);
		}
	}
	
	protected <V> String getServiceName(Class<V> target) {
		
		String className = target.getName();
		
		className = className.substring(className.lastIndexOf('.') + 1).replace("Mapper", "");
		
		return StringUtil.toLowerByFirstChar(className).concat("ServiceImpl");
		
	}

	/**
	 * 处理单个数据
	 * 
	 * @return
	 */
	protected <C> List<LogContentWithBLOBs> parseSingleData(Field[] fields, String tableName, Class<C> target,
			Object param, Long logId) {

		String name;

		Object value;

		List<LogContentWithBLOBs> logContents = new ArrayList<>();

		LogContentWithBLOBs content;

		Map<String, String> tableColumn = SpringBeanUtil.getBean(ITableColumnInfoService.class)
				.getTableComment(tableName);

		try {

			long time = System.currentTimeMillis() / 1000;

			for (int i = 0; i < fields.length; i++) {

				if (Modifier.isStatic(fields[i].getModifiers())) {
					continue;
				}

				name = fields[i].getName();

				if (name.equals("updateTime")) {
					continue;
				}

				value = this.getPropertyValue(name, target, param);

				if (null == value) {
					value = "";
				}

				content = new LogContentWithBLOBs();

				content.setComment(tableColumn.get(name));

				content.setCreateTime(time);

				content.setId(0L);

				content.setKey(name);

				content.setLogId(logId);

				content = this.parseContentWithBLOBs(content, "", value);

				logContents.add(content);
			}
			return logContents;

		} catch (Exception e) {
			// TODO: handle exception
			throw new Error(e.getMessage());
		}
	}

	/**
	 * 处理日志内容
	 * 
	 * @param content  日志实体
	 * @param oldValue 老值
	 * @param newValue 新值
	 * @return
	 */
	protected LogContentWithBLOBs parseContentWithBLOBs(LogContentWithBLOBs content, Object oldValue, Object newValue) {
		throw new Error("请实现方法");
	}
}
